#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("进程调度模拟器 (Process Scheduling Simulator)");

    // 初始化表格视图
    setupTableViews();

    // 初始化模拟器定时器
    simulationTimer = new QTimer(this);
    connect(simulationTimer, &QTimer::timeout, this, &MainWindow::updateSimulation);

    // 默认选择动态优先级算法
    ui->priorityRadioButton->setChecked(true);
    currentAlgorithm = Priority;
    ui->timeSliceSpinBox->setEnabled(false); // 时间片设置默认禁用
}

MainWindow::~MainWindow()
{
    delete ui;
    
    if (runningProcess) {
        delete runningProcess;
        runningProcess = nullptr;
    }
}

// 初始化表格的表头和模型
void MainWindow::setupTableViews()
{
    readyModel = new QStandardItemModel(this);
    runningModel = new QStandardItemModel(this);
    finishedModel = new QStandardItemModel(this);

    QStringList headers = {"进程名", "状态", "优先级", "总时间", "已用时间", "仍需时间"};
    readyModel->setHorizontalHeaderLabels(headers);
    runningModel->setHorizontalHeaderLabels(headers);
    finishedModel->setHorizontalHeaderLabels(headers);

    ui->readyTableView->setModel(readyModel);
    ui->runningTableView->setModel(runningModel);
    ui->finishedTableView->setModel(finishedModel);
    
    ui->readyTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ui->runningTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ui->finishedTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
}

// 当 "添加进程" 按钮被点击
void MainWindow::on_addProcessButton_clicked()
{
    QString name = ui->nameLineEdit->text();
    int time = ui->timeSpinBox->value();

    if (name.isEmpty() || time <= 0) {
        QMessageBox::warning(this, "输入错误", "进程名不能为空且需要时间必须大于0。");
        return;
    }

    for (const PCB &p : initialProcesses) {
        if (p.name == name) {
            QMessageBox::warning(this, "输入错误", "进程名已存在，请使用其他名称。");
            return;
        }
    }

    PCB p;
    p.name = name;
    p.totalTime = time;
    p.neededTime = time;
    p.cpuTime = 0;
    p.priority = 0;
    p.state = "就绪";
    
    initialProcesses.append(p);
    updateViews();
    ui->nameLineEdit->clear();
    ui->timeSpinBox->setValue(1);
}

// 当 "开始模拟" 按钮被点击
void MainWindow::on_startButton_clicked()
{
    if (initialProcesses.isEmpty()) {
        QMessageBox::information(this, "提示", "请先添加至少一个进程。");
        return;
    }
    
    readyQueue = initialProcesses;

    if (currentAlgorithm == Priority) {
        for (PCB &p : readyQueue) {
            p.priority = 50 - p.totalTime;
            if (p.priority < 0) p.priority = 0;
        }
    } else {
         for (PCB &p : readyQueue) {
            p.priority = 0;
        }
    }
    
    setControlsEnabled(false);
    simulationTime = 0; // 重置时间

    // 根据复选框决定运行模式
    if (ui->visualModeCheckBox->isChecked()) {
        // 可视化模式：启动定时器
        simulationTimer->start(500); 
    } else {
        // 纯计算模式：直接循环运行至结束
        while (!readyQueue.isEmpty() || runningProcess != nullptr) {
            runSingleStep();
        }
        // 模拟结束后更新UI并显示结果
        updateViews();
        QMessageBox::information(this, "模拟结束", QString("所有进程已在 %1 个时间单位内完成。").arg(simulationTime));
        setControlsEnabled(true);
    }
}

// 当 "重置" 按钮被点击
void MainWindow::on_resetButton_clicked()
{
    simulationTimer->stop();
    resetSimulation();
    setControlsEnabled(true);
}

// 当选择“时间片轮转”单选框
void MainWindow::on_roundRobinRadioButton_toggled(bool checked)
{
    ui->timeSliceSpinBox->setEnabled(checked);
    if(checked) {
        currentAlgorithm = RoundRobin;
    } else {
        currentAlgorithm = Priority;
    }
}

// 执行一个模拟时间单位的核心逻辑
void MainWindow::runSingleStep()
{
    simulationTime++;

    if (currentAlgorithm == Priority) {
        // 1. 如果CPU空闲，则先从就绪队列选择一个新进程
        if (!runningProcess && !readyQueue.isEmpty()) {
            int highestPriority = -1;
            int selectedIndex = -1;
            for(int i = 0; i < readyQueue.size(); ++i) {
                if(readyQueue[i].priority > highestPriority) {
                    highestPriority = readyQueue[i].priority;
                    selectedIndex = i;
                }
            }
            if (selectedIndex != -1) {
                 runningProcess = new PCB(readyQueue.takeAt(selectedIndex));
                 runningProcess->state = "运行";
            }
        }
        
        // 2. 如果当前有进程在运行，则执行它
        if (runningProcess) {
            runningProcess->cpuTime++;
            runningProcess->neededTime--;
            runningProcess->priority -= runningProcess->cpuTime; 
            
            // 3. 检查运行的进程是否完成
            if (runningProcess->neededTime == 0) {
                runningProcess->state = "完成";
                finishedQueue.append(*runningProcess);
                delete runningProcess;
                runningProcess = nullptr;
            }
        }

        // 4. 更新仍在就绪队列中等待的进程的优先级
        for (PCB &p : readyQueue) {
            p.priority++;
        }

    } else { // 时间片轮转
        // 1. 如果CPU空闲，则先从就绪队列选择一个新进程
        if (!runningProcess && !readyQueue.isEmpty()) {
            runningProcess = new PCB(readyQueue.takeFirst());
            runningProcess->state = "运行";
            timeSliceCounter = 0;
        }

        // 2. 如果当前有进程在运行，则执行它
        if (runningProcess) {
            runningProcess->cpuTime++;
            runningProcess->neededTime--;
            timeSliceCounter++;

            // 3. 检查进程是否完成，或时间片是否用完
            if (runningProcess->neededTime == 0) {
                runningProcess->state = "完成";
                finishedQueue.append(*runningProcess);
                delete runningProcess;
                runningProcess = nullptr;
            } 
            else if (timeSliceCounter == ui->timeSliceSpinBox->value()) {
                runningProcess->state = "就绪";
                readyQueue.append(*runningProcess);
                delete runningProcess;
                runningProcess = nullptr;
            }
        }
    }
}

// QTimer 触发的槽函数（仅用于可视化模式）
void MainWindow::updateSimulation()
{
    runSingleStep();
    updateViews();

    if (readyQueue.isEmpty() && runningProcess == nullptr) {
        simulationTimer->stop();
        QMessageBox::information(this, "模拟结束", QString("所有进程已在 %1 个时间单位内完成。").arg(simulationTime));
        setControlsEnabled(true);
    }
}

// 根据队列数据刷新所有表格视图
void MainWindow::updateViews()
{
    // 在纯计算模式下，时间标签需要最后更新
    ui->timeLabel->setText(QString("模拟时间: %1").arg(simulationTime));
    
    readyModel->removeRows(0, readyModel->rowCount());
    runningModel->removeRows(0, runningModel->rowCount());
    finishedModel->removeRows(0, finishedModel->rowCount());

    // 如果是可视化模式并且正在运行，显示实时就绪队列
    // 否则显示初始进程列表(模拟开始前)或最终空的就绪队列(计算模式结束后)
    const QList<PCB>& queueToShow = (simulationTimer->isActive() || !ui->visualModeCheckBox->isChecked()) ? readyQueue : initialProcesses;
    for (const PCB &p : queueToShow) {
        QList<QStandardItem *> row;
        row << new QStandardItem(p.name) << new QStandardItem(p.state) << new QStandardItem(QString::number(p.priority))
            << new QStandardItem(QString::number(p.totalTime)) << new QStandardItem(QString::number(p.cpuTime))
            << new QStandardItem(QString::number(p.neededTime));
        readyModel->appendRow(row);
    }
    
    if (runningProcess) {
        QList<QStandardItem *> row;
        row << new QStandardItem(runningProcess->name) << new QStandardItem(runningProcess->state) << new QStandardItem(QString::number(runningProcess->priority))
            << new QStandardItem(QString::number(runningProcess->totalTime)) << new QStandardItem(QString::number(runningProcess->cpuTime))
            << new QStandardItem(QString::number(runningProcess->neededTime));
        runningModel->appendRow(row);
    }

    for (const PCB &p : finishedQueue) {
        QList<QStandardItem *> row;
        row << new QStandardItem(p.name) << new QStandardItem(p.state) << new QStandardItem(QString::number(p.priority))
            << new QStandardItem(QString::number(p.totalTime)) << new QStandardItem(QString::number(p.cpuTime))
            << new QStandardItem(QString::number(p.neededTime));
        finishedModel->appendRow(row);
    }
}

// 重置所有状态和视图
void MainWindow::resetSimulation()
{
    if (runningProcess) {
        delete runningProcess;
        runningProcess = nullptr;
    }
    initialProcesses.clear();
    readyQueue.clear();
    finishedQueue.clear();

    simulationTime = 0;
    timeSliceCounter = 0;
    
    ui->timeLabel->setText("模拟时间: 0");
    updateViews();
}

// 设置输入和控制区域控件的可用性
void MainWindow::setControlsEnabled(bool enabled)
{
    ui->inputGroup->setEnabled(enabled);
    ui->controlGroup->setEnabled(enabled);
}
